<template>
    <!-- <div :id="id" class="chart-box"></div> -->
    <div ref="chartRef" class="chart"></div>
    <!-- <el-empty description="描述文字"></el-empty> -->
</template>

<script>
import optionsMap from './options.js';
import themeMap from './theme/themeMap.js';
// import dark from './theme/config/dark.js';
const elementResizeDetectorMaker = require("element-resize-detector");
const erd = elementResizeDetectorMaker();
export default {
    name: 'Chart',
    props: {
        // 用于生成echarts的domid，唯一
        id: {
            type: String,
        },
        config: {
            type: Object,
        },
    },
    watch: {
        config: {
            handler(config) {
                if (config) {
                    this.clear();
                    this.drawDiyChart(config);
                }
            },
            deep: true,
            immediate: true,
        },
    },
    data() {
        return {
            chart: null, // 用于储存生成的echarts实例
        };
    },
    mounted() {},
    beforeUnmount() {
        this.clear(); // 组件卸载前主动清除图表，防止内存泄漏
    },
    methods: {
        clear() {
            if (this.chart) this.chart.clear();
        },
        resize() {
            if (this.chart) this.chart.resize();
        },
        // 自定义图表
        async drawDiyChart(config) {
            // console.log('drawDiyChart：',config);
            let Option = {};
            if(config.database === '') {
                Option = config.demoOption.option;
            } else {
                // 存在数据源
                // alert(`url: ${config.database}`);
                await this.$api.post(config.database).then(res => {
                    console.log(res);
                    switch(config.chartType) {
                    case 'bar': Option = this.buildBarOrLine(res.data, config.chartType);
                        break;
                    case 'line': Option = this.buildBarOrLine(res.data, config.chartType);
                        break;
                    case 'top': Option = this.buildTop(res.data, config.chartType);
                        break;
                    default: Option = {};
                    }
                }).catch(()=>{
                    console.log('接口失败');
                });
            }
            // 基于准备好的dom，初始化echarts实例
            this.$nextTick(() => {
                const Dom = this.$refs.chartRef;
                this.$echarts.registerTheme(config.theme, themeMap[config.theme]);
                let myChart = this.$echarts.init(Dom, config.theme);
                console.log(myChart);
                // 绘制图表
                myChart.setOption(Option);
                this.chart = myChart;
                erd.listenTo(Dom, () => {
                    // var width = element.offsetWidth;
                    // var height = element.offsetHeight;
                    // console.log("Size: " + width + "x" + height);
                    this.resize();
                });
                window.addEventListener('resize', this.resize);
            });
        },
        buildBarOrLine(data, chartType) { // 解析柱状图
            // 获取基础配置
            let Option = optionsMap[chartType];
            //获取图例-legend
            let legendData = [];
            Object.keys(data.fieldMap).forEach((key, i) => {
                // 跳过第一个时间字段，添加图例名称
                if (i !== 0) legendData.push(data.fieldMap[key]);
            });
            Option.legend.data = legendData;
            // 根据X轴字段，获取X轴
            let xAxisData = [];
            data.list.forEach(rowList => {
                console.log(rowList);
                xAxisData.push(rowList[0]); // 第一项为时间项
            });
            Option.xAxis[0].data = xAxisData;
            let series = [];
            // 复制分类数据模板
            const serObj = JSON.parse(JSON.stringify(Option.series[0]));
            legendData.forEach( (barName, index) => {
                const bar = [];
                data.list.forEach( rowList => {
                    bar.push(rowList[index+1]);
                });
                serObj.name = barName;
                serObj.data = bar;
                const Item ={};
                Object.assign(Item,serObj);
                series.push(Item);
            });
            Option.series = series;
            return Option;
        },
        buildTop(data, chartType) { // 解析排行图, 聚合时间-取总数
            // 获取基础配置
            let Option = optionsMap[chartType];
            let legendData = [];
            Object.keys(data.fieldMap).forEach((key, i) => {
                // 跳过第一个时间字段，添加图例名称
                if (i !== 0) legendData.push(data.fieldMap[key]);
            });
            let seriesData = [];
            legendData.forEach( (topName, index) => {
                const topList = [];
                data.list.forEach( rowList => {
                    topList.push(rowList[index+1]);
                });
                console.log(topList);
                let topNum = 0;
                topList.forEach(num => topNum+=num);
                seriesData.push({
                    topName,
                    topNum
                });
            });

            // 获取完初始总计后，进行排序
            seriesData.sort((a,b)=>{
                return b.topNum - a.topNum;
            });
            seriesData.map((item)=>{
                Option.yAxis.data.push(item.topName);
                Option.series[0].data.push(item.topNum);
            });
            return Option;
        },

        buildStack(stackList, code) { // 堆叠函数
            let stackName = '';
            for(let i=0;i<stackList.length;i++) {
                const stack = stackList[i];
                const isStack = stack.list.some(value => {
                    // 此堆叠组是否包含这个样例
                    return code === value;
                });
                if (isStack) return stackName = stack.stackName;
            }
            return stackName;
        },
        // xxxxxxxxxxxxxxxxxxxx 暂时不做处理的函数 xxxxxxxxxxxxxxxxxx
        // 图表处理函数，入参config参考第6行注释
        drawChart(config) {
            this.$nextTick(() => {
                const { theme, chartType } = config;
                // id、chartType为必填项，注意：id需要props传递
                if (!this.id && !chartType) return this.$message.error('echarts缺少必要参数！');

                const Dom = document.getElementById(this.id);
                // 如果主题存在，则注册主题。主题样式优先级低于自定义样式。
                if (theme) this.$echarts.registerTheme(theme, themeMap[theme]);
                let myChart = this.$echarts.init(Dom, theme);
                // 绘制图表
                let option = {};
                // 根据chartType提取配置模板
                if (chartType === 'Line' || chartType === 'Bar') {
                    option = this.makeLineOrBar(config);
                } else if (chartType === 'Pie') {
                    option = this.makePie(config);
                }
                myChart.setOption(option);
                this.chart = myChart;
                erd.listenTo(Dom, () => {
                    // var width = element.offsetWidth;
                    // var height = element.offsetHeight;
                    // console.log("Size: " + width + "x" + height);
                    this.resize();
                });
                window.addEventListener('resize', this.resize);
            });
        },
        makeLineOrBar(config) {
            const { data, chartType, categoryBase } = config;
            // 判断数据的格式类型是否为品类基准。
            if (categoryBase) {
                return this.handleTimeBaseToLine(config);
            }
            // 类目集合 - 用于X轴
            const cols = Object.keys(data);
            // 获取基础配置
            const option = optionsMap[chartType];
            // 设置模板
            const sItemModel = JSON.parse(JSON.stringify(option.series[0]));
            if (config.flipXY) {
                // 翻转X轴和Y轴，默认以X轴为类目轴
                option.xAxis = { type: 'value' };
                option.yAxis = {
                    type: 'category',
                    data: cols,
                };
            } else {
                option.xAxis.data = cols;
            }
            // 配置series模板,写入数据
            const seriesModel = [];
            // 一个类目下的样例个数
            const group = data[cols[0]].map((t) => {
                return t.name;
            });

            group.forEach((g, gIndex) => {
                const valArr = [];
                cols.forEach((col) => {
                    valArr.push(data[col][gIndex].value);
                });

                seriesModel.push(Object.assign({}, sItemModel, { data: valArr, name: g }));
            });
            // 写入数据
            option.series = seriesModel;
            return option;
        },
        makePie(config) {
            // 获取基础配置
            const { data, chartType, categoryBase } = config;
            // 判断数据的格式类型是否为品类基准。
            if (categoryBase) {
                return this.handleTimeBaseToPie(config);
            }
            const option = optionsMap[chartType];
            const cols = Object.keys(data);
            // 一个类目下的样例个数
            const group = data[cols[0]].map((t) => {
                return t.name;
            });
            const seriesArr = [];
            group.forEach((g, gIndex) => {
                let allVal = 0;
                cols.forEach((col) => {
                    let val = data[col][gIndex].value;
                    allVal += val;
                });
                seriesArr.push({
                    name: g,
                    value: allVal,
                });
            });
            option.series[0].data = seriesArr;
            return option;
        },
        handleTimeBaseToLine(config) {
            return config;
        },
        handleTimeBaseToPie(config) {
            return config;
        },
    },
};
</script>

<style lang="scss" scoped>
.chart {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
}
</style>
